import time
import os
from datetime import datetime
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from minio import Minio
from minio.error import S3Error
from jsonconfig import Config
from logconfig import logger

# 加载配置
config = Config()
minio_config = config.get_minio_config()
watch_path = config.get_watch_path()
file_monitor_config = config.get_file_monitor_config()
# logging_config = config.get_logging_config()


# 初始化 MinIO 客户端
minio_client = Minio(
    minio_config.get("endpoint", "8.137.58.206:9000"),
    access_key=minio_config.get("access_key", "9eBv4Rt6"),
    secret_key=minio_config.get("secret_key", "3a7W5Mz8"),
    secure=minio_config.get("secure", False)

)

class ImageUploadHandler(FileSystemEventHandler):
    def __init__(self, watch_path):
        self.watch_path = watch_path
        self.retry_queue = []
        self.extensions = file_monitor_config.get("extensions", [".jpg", ".png", ".jpeg", ".bmp"])
        self.stable_check_interval = file_monitor_config.get("stable_check_interval", 1)
        self.max_stable_wait = file_monitor_config.get("max_stable_wait", 10)
        self.max_retries = file_monitor_config.get("max_retries", 3)
        self.bucket_name = minio_config.get("bucket_name", "bucket1")

        # 确保MinIO桶存在
        self.ensure_bucket_exists(self.bucket_name)
        logger.info(f"初始化监控器，监控路径: {watch_path}")

    def ensure_bucket_exists(self, bucket_name):
        try:
            if not minio_client.bucket_exists(bucket_name):
                minio_client.make_bucket(bucket_name)
                logger.info(f"创建桶: {bucket_name}")
            else:
                logger.info(f"桶已存在: {bucket_name}")
        except S3Error as err:
            logger.error(f"检查桶失败: {err}")

    def wait_for_file_stable(self, file_path):
        """等待文件大小稳定"""
        size = -1
        wait_time = 0
        while wait_time < self.max_stable_wait:
            try:
                current_size = os.path.getsize(file_path)
            except OSError:
                current_size = -1
            if current_size == size:
                return True
            size = current_size
            time.sleep(self.stable_check_interval)
            wait_time += self.stable_check_interval
        return False

    def on_created(self, event):
        file_path = event.src_path
        if not event.is_directory and any(file_path.lower().endswith(ext) for ext in self.extensions):
            logger.info(f"检测到新文件: {file_path}")
            # 等待文件完全写入
            if self.wait_for_file_stable(file_path):
                self.upload_file(file_path)
            else:
                logger.warning(f"文件未稳定，放弃上传: {file_path}")

    def upload_file(self, file_path):
        for attempt in range(self.max_retries):
            timestamp = str(int(time.time()))
            # 保留原始文件扩展名
            original_ext = os.path.splitext(file_path)[1].lower()
            object_name = timestamp + original_ext

            try:
                minio_client.fput_object(
                    self.bucket_name,
                    object_name,
                    file_path,
                    # content_type="image/jpeg"  # 显式指定内容类型
                )
                logger.info(f"图片 {file_path} 已成功上传为对象 {object_name}")
                os.remove(file_path)  # 删除本地文件
                return True
            except S3Error as err:
                logger.error(f"MinIO上传失败（尝试 {attempt + 1}/{self.max_retries}）: {err}")
            except Exception as e:
                logger.error(f"上传异常（尝试 {attempt + 1}/{self.max_retries}）: {e}")
            time.sleep(2 ** attempt)  # 指数退避
        logger.error(f"放弃上传，保留文件: {file_path}")
        return False

    def start_monitoring(self):
        """开始监控"""
        observer = Observer()
        observer.schedule(self, self.watch_path, recursive=False)
        observer.start()
        logger.info(f"开始监控目录: {self.watch_path}")
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            observer.stop()
            logger.info("监控已停止")
        observer.join()


# 使用示例
if __name__ == "__main__":
    handler = ImageUploadHandler(watch_path=watch_path)
    handler.start_monitoring()

